function [RDSingle, RDNeighborDiff, RDMin, RDOverall, base] = relatdiff(A, B, doSet2ToNaN, neighborDim, baseSmoothSpan, baseSmoothDim)
%RELATDIFF 求两个矩阵的相对差
%
% Tips
% # 对于随机变量，A、B对应元素均接近0可能导致RDSingle相对误差较大，这时RDNeighborDiff对应元素的大小可用于辅助排除上述情况
%
% Input Arguments
% # A, B: 尺寸相同的矩阵
% # doSet2ToNan: 将结果矩阵中为±2的元素设置为NaN，默认为false
% # neighborDim: 标量，计算RDNeighborDiff是所沿的维数
% # baseSmoothSpan: 基数（即相对差的分母(|A|+|B|)/2）平滑区间长度，当基数过零时可以利用数据的连续性做移动平均使基数变得稍大，从而减小相对差的数值，默认为1（不做移动平均）
% # baseSmoothDim: 基数平滑维数，一般为A、B中数据为连续的维数，默认为1
%
% Output Arguments
% # RDSingle: 尺寸与A、B相同的矩阵，A与B按元素计算的相对差，即(A-B)/[(|A|+|B|)/2]，若A某元素为正/负，B对应的元素为负/正，则C的对应元素为±2（若元素接近于0，较小的绝对误差可能导致±2的相对误差）
% # RDNeighborDiff: 尺寸与A、B相同的矩阵，neighborDim维相邻元素之差的相对差
% # RDMin: 各元素为单点相对差、前邻差相对差及后邻差相对差中绝对值最小的那一个
% # RDOverall: 标量，A、B各元素之差绝对值的均值与base绝对值均值之比，反映A、B整体相对误差
% # base: 尺寸与A、B相同的矩阵，经过平滑后的基数矩阵

if nargin < 6
    baseSmoothDim = 1;
end
if nargin < 5
    baseSmoothSpan = 1;
end
if nargin < 4
    neighborDim = 1;
end
if nargin < 3
    doSet2ToNaN = false;
end

base = (abs(A)+abs(B)) / 2;
if baseSmoothSpan > 1
    base = smooth_boundcond(base, baseSmoothSpan, baseSmoothDim);
end
RDSingle = (A-B) ./ (base);
if doSet2ToNaN
    RDSingle(abs(RDSingle)==2) = NaN;
end
if nargout > 1
    diffA = circdiff(A, 1, neighborDim);
    diffB = circdiff(B, 1, neighborDim);
    RDNeighborDiff = relatdiff(diffA, diffB);
    if doSet2ToNaN
        RDNeighborDiff(abs(RDNeighborDiff)==2) = NaN;
    end
    if nargout > 2
        RDMin = min_abs(RDSingle, RDNeighborDiff);
        RDMin = min_abs(RDMin, circshift(RDNeighborDiff, 1, neighborDim));
        if nargout > 3
            RDOverall = mean(abs(A(:)-B(:))) / mean(base(:));
        end
    end
end
end